package com.yowasa.xiuxian.engine;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.yowasa.xiuxian.annoations.CMD;
import com.yowasa.xiuxian.constant.LocalCache;
import com.yowasa.xiuxian.engine.callback.BaseCallBackHandler;
import com.yowasa.xiuxian.engine.message.BaseMessageHandler;
import com.yowasa.xiuxian.entity.bo.event.EventContent;
import com.yowasa.xiuxian.entity.bot.message.Message;
import com.yowasa.xiuxian.entity.enums.MapEnum;
import com.yowasa.xiuxian.entity.mys.ClickMsgComponent;
import com.yowasa.xiuxian.entity.mys.SendMessage;
import com.yowasa.xiuxian.exception.HandlerException;
import com.yowasa.xiuxian.service.helper.MessageHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.text.MessageFormat;
import java.util.List;
import java.util.Map;

/**
 * 消息引擎
 */
@Component
public class MessageEngine {
    public static final Logger logger = LoggerFactory.getLogger(MessageEngine.class);
    @Autowired
    private List<BaseMessageHandler> messageHandlers;
    @Autowired
    private List<BaseCallBackHandler> callBackHandlers;
    @Autowired
    private MessageHelper messageHelper;


    private BaseMessageHandler getMatchedHandler(SendMessage message) {
        String content = message.getContent();
        logger.info("====================================================");
        logger.info("content====================================================\n{}",content);
        JSONObject jsonObject = JSONUtil.parseObj(content);
        String text = (String) jsonObject.getJSONObject("content").get("text");
        logger.info("----------------------message----TEXT----into:\n{}",text);
        for (BaseMessageHandler messageHandler : messageHandlers) {
            if (messageHandler.match(text)) {
                return messageHandler;
            }
        }
        return null;
    }

    private BaseCallBackHandler getMatchedCallBackServer(String key) {
        logger.info("回调执行类List：{}",callBackHandlers);
        for (BaseCallBackHandler callBackHandler : callBackHandlers) {
            logger.info("当前获取的执行类：{}",callBackHandler);
            if (callBackHandler.match(key)) {
                return callBackHandler;
            }
        }
        return null;
    }


    private void checkHandler(BaseMessageHandler matchedHandler,Message message) {
        try {
            CMD annotation = matchedHandler.getClass().getAnnotation(CMD.class);
            String cmd = annotation.name();
            if (StringUtils.isEmpty(cmd)) {
                return;
            }
            //判定界外命令
            if (!message.isDirectMessage()&&!annotation.outCmd()) {
                Map<MapEnum, String> row = CommonEngine.XIUXIAN_MAP.row(message.getGuildId());
                if (!row.values().contains(message.getChannelId())) {
                    throw new HandlerException("此指令只能在地图频道内使用（如无地图频道请联系频道主执行 /初始化修仙 指令添加地图频道 注:需要确保机器人具有管理员权限且有创建频道权限）");
                }
            }
        }catch (Exception e){
            return;
        }
    }


    private boolean resolveEvent(Message message) {
        EventContent event = LocalCache.EVENT_CACHE.getIfPresent(message.getAuthor().getId());
        if (event == null) {
            return false;
        }
        boolean removeFlag = false;
        for (int i = 0; i < event.getActions().size(); i++) {
            EventContent.EventAction e = event.getActions().get(i);
            if (message.getContent().equals(e.getCmd())) {
                e.getActionRun().exec();
                removeFlag = true;
                break;
            }
        }
        if (removeFlag) {
            LocalCache.EVENT_CACHE.invalidate(message.getAuthor().getId());
        } else {
            return event.isBlock();
        }
        return false;
    }

    public void resolveMessageMys(SendMessage sendMessage) {
        try {
            // 获取指令对应的执行类

            BaseMessageHandler matchedHandler = getMatchedHandler(sendMessage);
            // todo 指令是否可执行校验 按指令类注解反射判断，后期根据业务修改
//            checkHandler(matchedHandler,sendMessage);
            if (matchedHandler != null) {
                // 获取匹配到了对应的执行类，调用业务方法
                logger.info("开始执行方法：{}",sendMessage.getContent());
                matchedHandler.execute(sendMessage);
            }
        } catch (HandlerException e) {
            // 产生异常，调用指令推送方法
            messageHelper.replyMys(sendMessage, MessageFormat.format("指令执行失败，原因：{0}", e.getMessage()));
        }
    }

    public void resolveClickMessageMys(ClickMsgComponent clickMsgComponent) {
        try {
            JSONObject jsonObject = JSONUtil.parseObj(clickMsgComponent.getExtra());
            String key =  jsonObject.getStr("key");
            logger.info("回调匹配key：{}",key);
            BaseCallBackHandler matchedCallBackServer = getMatchedCallBackServer(key);
            matchedCallBackServer.execute(clickMsgComponent);
        } catch (HandlerException e) {
            // 产生异常，调用指令推送方法
            SendMessage sendMessage = new SendMessage();
            sendMessage.setVilla_id(clickMsgComponent.getVilla_id());
            sendMessage.setRoom_id(clickMsgComponent.getRoom_id());
            messageHelper.replyMys(sendMessage, MessageFormat.format("指令执行失败，原因：{0}", e.getMessage()));
        }
    }
}
